﻿#include "FITKAbaqusHDF5AdaptorConstraint.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"

#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Writer.h"

#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractMaterial.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractSection.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKSectionAssign.h"

#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractConstraint.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConstraintTie.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConstraintRigidBody.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConstraintCoupling.h"

namespace IO
{
    QString FITKAbaqusHDF5AdaptorConstraint::getAdaptorClass()
    {
        return "FITKAbaqusHDF5AdaptorConstraint";
    }

    bool FITKAbaqusHDF5AdaptorConstraint::adaptR()
    {
        auto constraint = dynamic_cast<Interface::FITKAbaAbstractConstraint*>(_dataObj);
        if (!_reader || !_h5Group || !constraint) return false;
        bool isR = true;
        isR &= readConstraint(constraint, *_h5Group);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::adaptW()
    {
        auto constraint = dynamic_cast<Interface::FITKAbaAbstractConstraint*>(_dataObj);
        if (!_writer || !_h5Group || !constraint) return false;
        bool isW = true;
        isW &= writeConstraint(constraint, *_h5Group);
        return isW;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::readConstraint(Interface::FITKAbaAbstractConstraint * constraint, H5::Group & h5Group)
    {
        if (!constraint) return false;
        bool isR = true;
        isR &= readNDataObject(constraint, h5Group);

        auto firstLocationGroup = h5Group.openGroup("FirstLocation");
        readBoundaryLocation(constraint->getFirstLocation(), firstLocationGroup);
        auto secondLocationGroup = h5Group.openGroup("SecondLocation");
        readBoundaryLocation(constraint->getSecondLocation(), secondLocationGroup);

        bool ActiveState = readBoolAttribute(h5Group, "ActiveState");
        constraint->setActiveState(ActiveState);

        auto ConstraintType = constraint->getConstraintType();
        if (ConstraintType == Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType::Coupling)
        {
            isR &= readCoupling(constraint, h5Group);
        }
        else if (ConstraintType == Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType::RigidBody)
        {
            isR &= readRigidBody(constraint, h5Group);
        }
        else if (ConstraintType == Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType::Tie)
        {
            isR &= readTie(constraint, h5Group);
        }
        else
        {
            return false;
        }
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::readCoupling(Interface::FITKAbaAbstractConstraint* constraint, H5::Group& h5Group)
    {
        auto coupling = dynamic_cast<Interface::FITKAbaConstraintCoupling*>(constraint);
        if (!coupling) return false;
        bool isValid = false;

        auto couplingType = readStrAttribute(h5Group, "CouplingType");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintCoupling::CouplingType> fitkCTypeTrafer;
        auto eCouplingType = fitkCTypeTrafer.fromString(QString::fromStdString(couplingType), isValid);
        if (!isValid) return false;
        coupling->setCouplingType(eCouplingType);

        bool U1 = readBoolAttribute(h5Group, "U1");
        coupling->setU1(U1);
        bool U2 = readBoolAttribute(h5Group, "U2");
        coupling->setU2(U2);
        bool U3 = readBoolAttribute(h5Group, "U3");
        coupling->setU3(U3);
        bool UR1 = readBoolAttribute(h5Group, "UR1");
        coupling->setUR1(UR1);
        bool UR2 = readBoolAttribute(h5Group, "UR2");
        coupling->setUR2(UR2);
        bool UR3 = readBoolAttribute(h5Group, "UR3");
        coupling->setUR3(UR3);

        auto weightingMethod = readStrAttribute(h5Group, "WeightingMethod");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintCoupling::WeightingMethod> fitkWTypeTrafer;
        auto eWeightingMethod = fitkWTypeTrafer.fromString(QString::fromStdString(weightingMethod), isValid);
        if (!isValid) return false;
        coupling->setWeightingMethod(eWeightingMethod);

        auto influenceRadius = readStrAttribute(h5Group, "InfluenceRadius");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintCoupling::InfluenceRadius> fitkITypeTrafer;
        auto eInfluenceRadius = fitkITypeTrafer.fromString(QString::fromStdString(influenceRadius), isValid);
        if (!isValid) return false;
        coupling->setInfluenceRadius(eInfluenceRadius);

        double InfluenceRadiusValue = readDoubleAttribute(h5Group, "InfluenceRadiusValue");
        coupling->setInfluenceRadiusValue(InfluenceRadiusValue);
        bool AdjustCentrolPoints = readBoolAttribute(h5Group, "AdjustCentrolPoints");
        coupling->setAdjustCentrolPoints(AdjustCentrolPoints);

        int CsysId = readIntAttribute(h5Group, "CsysId");
        coupling->setCsysId(CsysId);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::readRigidBody(Interface::FITKAbaAbstractConstraint* constraint, H5::Group& h5Group)
    {
        auto rigidBody = dynamic_cast<Interface::FITKAbaConstraintRigidBody*>(constraint);
        if (!rigidBody) return false;

        bool AdjustPoint = readBoolAttribute(h5Group, "AdjustPoint");
        rigidBody->setAdjustPoint(AdjustPoint);
        bool ConstraintSelectedRegionToBeIsothermal = readBoolAttribute(h5Group, "ConstraintSelectedRegionToBeIsothermal");
        rigidBody->setConstraintSelectedRegionToBeIsothermal(ConstraintSelectedRegionToBeIsothermal);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::readTie(Interface::FITKAbaAbstractConstraint* constraint, H5::Group& h5Group)
    {
        auto tie = dynamic_cast<Interface::FITKAbaConstraintTie*>(constraint);
        if (!tie) return false;
        bool isValid = false;

        auto discretizationMethod = readStrAttribute(h5Group, "DiscretizationMethod");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintTie::DiscretizationMethod> fitkDTypeTrafer;
        auto eDiscretizationMethod = fitkDTypeTrafer.fromString(QString::fromStdString(discretizationMethod), isValid);
        if (!isValid) return false;
        tie->setDiscretizationMethod(eDiscretizationMethod);

        bool ExcludeShellThickness = readBoolAttribute(h5Group, "ExcludeShellThickness");
        tie->setExcludeShellThickness(ExcludeShellThickness);

        auto PostionTolerance = readStrAttribute(h5Group, "PostionTolerance");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintTie::PositionTolerance> fitkPTypeTrafer;
        auto ePostionTolerance = fitkPTypeTrafer.fromString(QString::fromStdString(PostionTolerance), isValid);
        if (!isValid) return false;
        tie->setPostionTol(ePostionTolerance);

        double PositionDistance = readDoubleAttribute(h5Group, "PositionDistance");
        tie->setPositionDistance(PositionDistance);

        bool AdjustSlave = readBoolAttribute(h5Group, "AdjustSlave");
        tie->setAdjustSlave(AdjustSlave);

        bool TieRotationDofs = readBoolAttribute(h5Group, "TieRotationDofs");
        tie->setTieRotationDofs(TieRotationDofs);

        auto ConstraintRatio = readStrAttribute(h5Group, "ConstraintRatio");
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintTie::ConstraintRatio> fitkCTypeTrafer;
        auto eConstraintRatio = fitkCTypeTrafer.fromString(QString::fromStdString(ConstraintRatio), isValid);
        if (!isValid) return false;
        tie->setConstraintRatio(eConstraintRatio);

        double ConstraintRatioValue = readDoubleAttribute(h5Group, "ConstraintRatioValue");
        tie->setConstraintRatioValue(ConstraintRatioValue);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::writeConstraint(Interface::FITKAbaAbstractConstraint * constraint, H5::Group & h5Group)
    {
        if (!constraint) return false;
        bool isW = true;
        bool isValid = false;

        std::string groupName = createParentAttribute(constraint, h5Group);
        if (groupName.empty())return false;

        auto constraintGroup = h5Group.createGroup(groupName);

        auto firstLocationGroup = constraintGroup.createGroup("FirstLocation");
        writeBoundaryLocation(constraint->getFirstLocation(), firstLocationGroup);
        auto secondLocationGroup = constraintGroup.createGroup("SecondLocation");
        writeBoundaryLocation(constraint->getSecondLocation(), secondLocationGroup);

        bool ActiveState = constraint->getActiveState();
        writeBoolAttribute(constraintGroup, "ActiveState", &ActiveState);

        auto ConstraintType = constraint->getConstraintType();
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType> fitkCTypeTrafer;
        QString sType = fitkCTypeTrafer.toStrting(ConstraintType, isValid);
        if (!isValid) return false;
        writeStrAttribute(constraintGroup, "Type", sType.toStdString());

        if (ConstraintType == Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType::Coupling)
        {
            isW &= writeCoupling(constraint, constraintGroup);
        }
        else if (ConstraintType == Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType::RigidBody)
        {
            isW &= writeRigidBody(constraint, constraintGroup);
        }
        else if (ConstraintType == Interface::FITKAbaAbstractConstraint::FITKAbaConstraintType::Tie)
        {
            isW &= writeTie(constraint, constraintGroup);
        }
        else
        {
            return false;
        }
        isW &= writeNDataObject(constraint, constraintGroup);

        return isW;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::writeCoupling(Interface::FITKAbaAbstractConstraint * constraint, H5::Group & h5Group)
    {
        auto coupling = dynamic_cast<Interface::FITKAbaConstraintCoupling*>(constraint);
        if (!coupling) return false;
        bool isValid = false;

        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintCoupling::CouplingType> fitkCTypeTrafer;
        auto eCouplingType = fitkCTypeTrafer.toStrting(coupling->couplingType(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "CouplingType", eCouplingType.toStdString());

        bool U1 = coupling->getU1();
        writeBoolAttribute(h5Group, "U1", &U1);
        bool U2 = coupling->getU2();
        writeBoolAttribute(h5Group, "U2", &U2);
        bool U3 = coupling->getU3();
        writeBoolAttribute(h5Group, "U3", &U3);
        bool UR1 = coupling->getUR1();
        writeBoolAttribute(h5Group, "UR1", &UR1);
        bool UR2 = coupling->getUR2();
        writeBoolAttribute(h5Group, "UR2", &UR2);
        bool UR3 = coupling->getUR3();
        writeBoolAttribute(h5Group, "UR3", &UR3);

        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintCoupling::WeightingMethod> fitkWTypeTrafer;
        auto eWeightingMethod = fitkWTypeTrafer.toStrting(coupling->getWeightingMethod(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "WeightingMethod", eWeightingMethod.toStdString());

        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintCoupling::InfluenceRadius> fitkITypeTrafer;
        auto eInfluenceRadius = fitkITypeTrafer.toStrting(coupling->getInfluenceRadius(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "InfluenceRadius", eInfluenceRadius.toStdString());

        double InfluenceRadiusValue = coupling->getInfluenceRadiusValue();
        writeDoubleAttribute(h5Group, "InfluenceRadiusValue", &InfluenceRadiusValue);
        bool AdjustCentrolPoints = coupling->getAdjustCentrolPoints();
        writeBoolAttribute(h5Group, "AdjustCentrolPoints", &AdjustCentrolPoints);
        int CsysId = coupling->getCsysId();
        writeIntAttribute(h5Group, "CsysId", &CsysId);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::writeRigidBody(Interface::FITKAbaAbstractConstraint * constraint, H5::Group & h5Group)
    {
        auto rigidBody = dynamic_cast<Interface::FITKAbaConstraintRigidBody*>(constraint);
        if (!rigidBody) return false;

        bool AdjustPoint = rigidBody->getAdjustPoint();
        writeBoolAttribute(h5Group, "AdjustPoint", &AdjustPoint);

        bool ConstraintSelectedRegionToBeIsothermal = rigidBody->getConstraintSelectedRegionToBeIsothermal();
        writeBoolAttribute(h5Group, "ConstraintSelectedRegionToBeIsothermal", &ConstraintSelectedRegionToBeIsothermal);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorConstraint::writeTie(Interface::FITKAbaAbstractConstraint * constraint, H5::Group & h5Group)
    {
        auto tie = dynamic_cast<Interface::FITKAbaConstraintTie*>(constraint);
        if (!tie) return false;

        bool isValid = false;
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintTie::DiscretizationMethod> fitkDTypeTrafer;
        auto eDiscretizationMethod = fitkDTypeTrafer.toStrting(tie->getDiscretizationMethod(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "DiscretizationMethod", eDiscretizationMethod.toStdString());

        bool ExcludeShellThickness = tie->getExcludeShellThickness();
        writeBoolAttribute(h5Group, "ExcludeShellThickness", &ExcludeShellThickness);
        
        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintTie::PositionTolerance> fitkPTypeTrafer;
        auto ePostionTolerance = fitkPTypeTrafer.toStrting(tie->getPostionTolerance(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "PostionTolerance", ePostionTolerance.toStdString());
        
        double PositionDistance = tie->getPositionDistance();
        writeDoubleAttribute(h5Group, "PositionDistance", &PositionDistance);
        bool AdjustSlave = tie->getAdjustSlave();
        writeBoolAttribute(h5Group, "AdjustSlave", &AdjustSlave);
        bool TieRotationDofs = tie->getTieRotationDofs();
        writeBoolAttribute(h5Group, "TieRotationDofs", &TieRotationDofs);

        //枚举转换字符
        Core::FITKEnumTransfer<Interface::FITKAbaConstraintTie::ConstraintRatio> fitkCTypeTrafer;
        auto eConstraintRatio = fitkCTypeTrafer.toStrting(tie->getConstraintRatio(), isValid);
        if (!isValid) return false;
        writeStrAttribute(h5Group, "ConstraintRatio", eConstraintRatio.toStdString());

        double ConstraintRatioValue = tie->getConstraintRatioValue();
        writeDoubleAttribute(h5Group, "ConstraintRatioValue", &ConstraintRatioValue);

        return true;
    }

}